﻿package kliment.net {
	import flash.events.EventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.net.NetConnection;
	import flash.net.ObjectEncoding;

	import kliment.events.AMFConnectEvent;
	import kliment.events.AMFResponderEvent;

	[Event(name = 'response', type = 'kliment.events.AMFResponderEvent')]

	[Event(name = 'netStatus', type = 'kliment.events.AMFResponderEvent')]

	/**
	 * ...
	 * @author Kliment
	 * @version 1.1.6
	 *
	 * class name: kliment.net.AMFConnect
	 */
	public class AMFConnect extends EventDispatcher {
		private var _netConnection:NetConnection;
		private var _queue:Array;

		public var debugEnabled:Boolean = false;

		public function AMFConnect(gateway:String) {
			_queue = new Array();
			_netConnection = new NetConnection();
			_netConnection.addEventListener(NetStatusEvent.NET_STATUS, _netStatusHandler);
			_netConnection.objectEncoding = ObjectEncoding.AMF3;
			_netConnection.connect(gateway);
		}

		public function get encoding():uint { return _netConnection.objectEncoding; }
		public function set encoding(value:uint):void {
			_netConnection.objectEncoding = value;
		}

		public function call(method:String, ...args):AMFResponder {
			var responder:AMFResponder = new AMFResponder();
			responder.addEventListener(AMFResponderEvent.COMPLETE, _responderHandler);
			//if (debugEnabled)
			{
				responder.addEventListener(AMFResponderEvent.ERROR, _responderHandler);
			}
			responder.parameters = args;
			_queue.push([method, responder].concat(args));
			if (_queue.length == 1)
				_callNext();
			return responder;
		}

		private function _callNext():void {
			if (_queue.length)
				_netConnection.call.apply(null, _queue[0]);
		}

		private function _responderHandler(event:AMFResponderEvent):void {
			var eventTarget:AMFResponder = event.target as AMFResponder;
			eventTarget.removeEventListener(AMFResponderEvent.COMPLETE, _responderHandler);
			eventTarget.removeEventListener(AMFResponderEvent.ERROR, _responderHandler);
			switch(event.type) {
				case AMFResponderEvent.COMPLETE:
					_queue.shift();
					_callNext();
				break;

				case AMFResponderEvent.ERROR:
					if (debugEnabled)
					{
						_queue.shift();
						_callNext();
					}
				break;
			}
			dispatchEvent(new AMFConnectEvent(AMFConnectEvent.RESPONSE, event.clone()));
		}

		private function _netStatusHandler(event:NetStatusEvent):void {
			switch (event.info.level)
			{
				case "error":
					//
				break;
				case "status":
					//
				break;
				default:
					//
				break;
			}
			switch (event.info.code)
			{
				case "NetConnection.Call.Failed":
					//
				break;
				default:
					//
				break;
			}
			dispatchEvent(new AMFConnectEvent(AMFConnectEvent.NET_STATUS, event.clone()));
		}

		public function close():void {
			_netConnection.close();
		}
	}

}